using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Globalization;

namespace Toenda.Foundation.Data {
	/// <summary>
	/// Class UdlParser
	/// </summary>
	public class UdlParser {
		private string _buffer;
		private DALSettings _db;

		/// <summary>
		/// Default Ctor
		/// </summary>
		public UdlParser() {
			this._db = new DALSettings();
		}

		/// <summary>
		/// Specific Ctor
		/// </summary>
		/// <param name="fileName">The name of the udl file.</param>
		public UdlParser(string fileName) {
			this._db = new DALSettings();

			this.ReadToConnectionStringLine(fileName);
		}

		/// <summary>
		/// Specific Ctor
		/// </summary>
		/// <param name="value">The value.</param>
		/// <param name="type">The type.</param>
		public UdlParser(string value, UdlParserParameterValueType type) {
			this._db = new DALSettings();

			if(type == UdlParserParameterValueType.FileName) {
				this.ReadToConnectionStringLine(value);
			}
			else if(type == UdlParserParameterValueType.ConnectionString) {
				this._buffer = value;
			}
		}

		/// <summary>
		/// Parse the udl file
		/// </summary>
		/// <returns></returns>
		public string ReadConnectionString() {
			this._db.ConnectionString = this._buffer;
			return this._db.ConnectionString;
		}

		/// <summary>
		/// Parse the udl file
		/// </summary>
		/// <returns></returns>
		public DALSettings Parse() {
			return this.InternalParse();
		}

		/// <summary>
		/// Parse the udl file
		/// </summary>
		/// <param name="fileName">The path and the filename</param>
		/// <returns></returns>
		public DALSettings Parse(string fileName) {
			if(fileName.IsNullOrTrimmedEmpty()) {
				return null;
			}

			fileName = CorrectFileName(fileName);

			if(fileName != null) {
				this.ReadToConnectionStringLine(fileName);

				return this.InternalParse();
			}
			else {
				return null;
			}
		}

		/// <summary>
		/// Parse a connectionString
		/// </summary>
		/// <param name="connectionString"></param>
		/// <returns></returns>
		public static DALSettings ParseConnectionString(string connectionString) {
			//this._buffer = connectionString;
			//return this._Parse(false);

			UdlParser parser = new UdlParser(connectionString, UdlParserParameterValueType.ConnectionString);
			return parser.Parse();
		}

		/// <summary>
		/// Correct the udl file name
		/// </summary>
		/// <param name="fileName"></param>
		/// <returns></returns>
		public static string CorrectFileName(string fileName) {
			if(!File.Exists(fileName) && fileName.IndexOf("\\", StringComparison.CurrentCulture) < 0) {
				// try to find udlfile automatically

				try {
					DirectoryInfo d = new DirectoryInfo(System.Reflection.Assembly.GetExecutingAssembly().Location);
					fileName = d.Parent.Parent.FullName + "\\dbconnect\\" + fileName;
				}
				catch(Exception) {
					return null;
				}
			}

			return fileName;
		}

		/// <summary>
		/// Read inside the buffer to the connection string
		/// </summary>
		/// <param name="fileName">The path/filename of the udl file.</param>
		private void ReadToConnectionStringLine(string fileName) {
			//[oledb]
			//; Everything after this line is an OLE DB initstring

			fileName = CorrectFileName(fileName);

			StreamReader sr = new StreamReader(fileName);
			//this._buffer = sr.ReadToEnd();

			while(!sr.EndOfStream) {
				string tmp = sr.ReadLine();

				if(!tmp.Trim().StartsWith(";", StringComparison.CurrentCulture)) {
					if(tmp.IndexOf("[oledb]", StringComparison.CurrentCulture) == -1) {
						this._buffer += tmp;
					}
				}
			}

			// TODO: Implement this!

			/*this._buffer.Replace("\n", "");
			this._buffer.Replace("\r", "");
			this._buffer.Replace("\t", "");

			if(!this._buffer.EndsWith(";")) {
				this._buffer += ";";
			}*/
		}

		/// <summary>
		/// Parse the file
		/// </summary>
		/// <returns></returns>
		private DALSettings InternalParse() {
			if(!this._buffer.IsNullOrTrimmedEmpty()) {
				string tmp = "", tmp2 = "";

				char[] sep = new char[1];
				sep[0] = ';';
				string[] sb = this._buffer.Split(sep);

				bool specialForSQLite = false;
				string removedDriver = "";

				foreach(string g in sb) {
					tmp2 = g.Trim();

					// provider
					if(tmp2.Length > 6) {
						tmp = null;
						if(tmp2.Length > 6 && tmp2.Substring(0, 7) == "Driver=") {
							tmp = tmp2.Substring(7);
						}
						else if(tmp2.Length > 8 && tmp2.Substring(0, 9) == "Provider=") {
							tmp = tmp2.Substring(9);
						}
						else if(tmp2.Length > 13 && tmp2.Substring(0, 14) == "Data Provider=") {
							tmp = tmp2.Substring(14);
						}

						if(!string.IsNullOrEmpty(tmp)) {
							switch(tmp) {
								case "SQLOLEDB.1":
								case "SQLOLEDB":
								case "{SQL Server}":
								case "{SQL Native Client}":
									this._db.ProviderType = ProviderType.MSSql2000;
									break;

								case "{mySQL}":
									this._db.ProviderType = ProviderType.MySql;
									break;

								case "SQLite":
									this._db.ProviderType = ProviderType.SQLite;
									specialForSQLite = true;
									removedDriver = tmp2;
									break;

								default:
									this._db.ProviderType = ProviderType.MSSql2000;
									break;
							}
						}
					}

					// Password
					if(tmp2.Length > 3 && tmp2.Substring(0, 4) == "Pwd=") {
						this._db.Password = tmp2.Substring(4);
					}
					else if(tmp2.Length > 8 && tmp2.Substring(0, 9) == "Password=") {
						this._db.Password = tmp2.Substring(9);
					}

					// Persist Security Info
					if(tmp2.Length > 21) {
						if(tmp2.Substring(0, 22) == "Persist Security Info=") {
							tmp = tmp2.Substring(22).ToLower(CultureInfo.CurrentCulture);
							this._db.PersistSecurityInfo = (tmp == "0" || tmp == "false" ? false : true);
						}
					}

					// Integrated Security
					if(tmp2.Length > 19) {
						if(tmp2.Substring(0, 20) == "Integrated Security=") {
							tmp = tmp2.Substring(20).ToLower(CultureInfo.CurrentCulture);
							this._db.IntegratedSecurity = (tmp == "0" || tmp == "false" ? false : true);
						}
					}

					// User ID
					if(tmp2.Length > 3 && tmp2.Substring(0, 4) == "Uid=") {
						this._db.User = tmp2.Substring(4);
					}
					else if(tmp2.Length > 7 && tmp2.Substring(0, 8) == "User ID=") {
						this._db.User = tmp2.Substring(8);
					}

					// Database
					if(tmp2.Length > 8 && tmp2.Substring(0, 9) == "Database=") {
						this._db.Database = tmp2.Substring(9);
					}
					else if(tmp2.Length > 15 && tmp2.Substring(0, 16) == "Initial Catalog=") {
						this._db.Database = tmp2.Substring(16);
					}

					// Server
					if(tmp2.Length > 6 && tmp2.Substring(0, 7) == "Server=") {
						this._db.Server = tmp2.Substring(7);
					}
					else if(tmp2.Length > 11 && tmp2.Substring(0, 12) == "Data Source=") {
						this._db.Server = tmp2.Substring(12);
					}

					// Port
					if(tmp2.Length > 4) {
						if(tmp2.Substring(0, 5) == "Port=") {
							this._db.Port = tmp2.Substring(5);
						}
					}

					// Trusted Connection
					if(tmp2.Length > 18) {
						if(tmp2.Substring(0, 19) == "Trusted_Connection=") {
							tmp = tmp2.Substring(19).ToLower(CultureInfo.CurrentCulture);
							this._db.TrustedConnection = (tmp == "0" || tmp == "false" ? false : true);
						}
					}

					// User Instance
					if(tmp2.Length > 13) {
						if(tmp2.Substring(0, 14) == "User Instance=") {
							tmp = tmp2.Substring(14).ToLower(CultureInfo.CurrentCulture);
							this._db.UserInstance = (tmp == "0" || tmp == "false" ? false : true);
						}
					}

					// MultipleActiveResultSets
					if(tmp2.Length > 24) {
						if(tmp2.Substring(0, 25) == "MultipleActiveResultSets=") {
							tmp = tmp2.Substring(25).ToLower(CultureInfo.CurrentCulture);
							this._db.MultipleActiveResultSets = (tmp == "0" || tmp == "false" ? false : true);
						}
					}

					// FailoverPartner
					if(tmp2.Length > 16) {
						if(tmp2.Substring(0, 17) == "Failover Partner=") {
							tmp = tmp2.Substring(17).ToLower(CultureInfo.CurrentCulture);
							this._db.FailoverPartner = tmp2.Substring(17);
						}
					}
				}

				if(specialForSQLite) {
					this._buffer = this._buffer.Replace(removedDriver + ";", "");
					this._db.ConnectionString = this._buffer;
				}
			}

			return this._db;
		}
	}
}
